package com.zd.springsecuritydemo.exception;

import com.zd.springsecuritydemo.response.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;

/**
 * @authoResponseResult wavesen
 * @version 1.0
 * @description: 全局异常捕获
 * @date 2024/1/2 18:00
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandlerResolver {

    @ExceptionHandler({Exception.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseResult handleGlobalException(Exception e) {
        log.error("全局异常信息 ex={}", e.getMessage(), e);
        return ResponseResult.fail("系统异常，请联系客服");
    }

    @ExceptionHandler({BusinessException.class, IllegalArgumentException.class})
    @ResponseStatus(HttpStatus.OK)
    public ResponseResult businessException(Exception e) {
        log.error("业务异常 ex={}", e.getMessage(), e);
        if (e instanceof BusinessException) {
            BusinessException businessException = (BusinessException) e;
            return ResponseResult.fail(businessException.getErrCode(), businessException.getLocalizedMessage());
        } else {
            return ResponseResult.fail(e.getLocalizedMessage());
        }
    }

    @ExceptionHandler({BadCredentialsException.class})
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ResponseResult handleBadCredentialsException(BadCredentialsException e) {
        String msg = SpringSecurityMessageSource.getAccessor().getMessage("handleBadCredentialsException", e.getMessage());
        log.error("认证失败 ex={}", msg, e);
        return ResponseResult.fail(HttpStatus.UNAUTHORIZED.value(), e.getLocalizedMessage());
    }

    @ExceptionHandler({AccessDeniedException.class})
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public ResponseResult handleAccessDeniedException(AccessDeniedException e) {
        String msg = SpringSecurityMessageSource.getAccessor().getMessage("AbstractAccessDecisionManageResponseResult.accessDenied", e.getMessage());
        log.error("拒绝授权异常信息 ex={}", msg, e);
        return ResponseResult.fail(HttpStatus.FORBIDDEN.value(), e.getLocalizedMessage());
    }

    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseResult handleBodyValidException(MethodArgumentNotValidException exception) {
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        log.error("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage());
        return ResponseResult.fail(fieldErrors.get(0).getDefaultMessage());
    }
}
